﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core.Profile;
using COFE.Core.Logger;
using COFE.Core.Lister;
using NUnit.Framework;
using System.ComponentModel.Composition;
using COFE.Core.Plugin;
using COFE.Core.EntryType;
using COFE.Core.Utils;
using COFE.Core.Filter;
using System.Reflection;
using COFE.Core.Entry;

namespace COFE.Core
{
    public static class COFEShared
    {

        #region Constructor

        static COFEShared()
        {
            PropertyDictionary = new PropertyDictionary();
            VolumeRegistrar = new VolumeRegistrar();
            MasterEventLogger = new MasterEventLogger();
        }

        #endregion

        #region Methods

        public static void Register()
        {
            if (!(COFEShared.VolumeRegistrar is VolumeRegistrar))
                COFEShared.VolumeRegistrar = new VolumeRegistrar();
            
            if (!(COFEShared.SecondaryPropertyProviderManager is SecondaryPropertyProviderManager))
                COFEShared.SecondaryPropertyProviderManager = new SecondaryPropertyProviderManager();

            if (!(COFEShared.PropertyDictionary is PropertyDictionary))
                COFEShared.PropertyDictionary = new PropertyDictionary();

            if (!(COFEShared.PathParser is BasicPathParser))
                COFEShared.PathParser = new BasicPathParser();

            if (!(COFEShared.EntryConstructor is EntryConstructor))
                COFEShared.EntryConstructor = new EntryConstructor();

            if (!(COFEShared.EntryListRegistrar is EntryListRegistrar))
                COFEShared.EntryListRegistrar = new EntryListRegistrar();

            if (!(COFEShared.UserProfileManager is NoUserManagementUserProfileManager))
                COFEShared.UserProfileManager = new NoUserManagementUserProfileManager();

            if (!(COFEShared.FileSystemEventDispatcher is FileSystemEventDispatcher))
                COFEShared.FileSystemEventDispatcher = new FileSystemEventDispatcher();

            COFEShared.EntryTypeDictionary = new EntryTypeDictionary(new EntryIconExtractor(), new EntryTypeFilterGenerator());

            COFEShared.PropertyDictionary.RegisterProperties<InternalProperties>();
            COFEShared.PropertyDictionary.RegisterProperties<FileSystemInfoProperties>();
            COFEShared.PropertyDictionary.RegisterProperties<FileInfoProperties>();
            COFEShared.PropertyDictionary.RegisterProperties<DirectoryInfoProperties>();
            COFEShared.PropertyDictionary.RegisterProperties<IconProperties>();


            FilterUtils2<IEntryFilter>.RegisterFilter(typeof(FileNameEntryFilter));
            FilterUtils2<IEntryFilter>.RegisterFilter(typeof(FileTypeEntryFilter));
            FilterUtils2<IEntryFilter>.RegisterFilter(typeof(GuidEntryFilter));
            FilterUtils2<IEntryFilter>.RegisterFilter(typeof(RootEntryFilter));
            FilterUtils2<IOptionFilter>.RegisterFilter(typeof(SearchOptionOptionFilter));
            FilterUtils2<IOptionFilter>.RegisterFilter(typeof(SearchSourceOptionFilter));
            FilterUtils2<IOptionFilter>.RegisterFilter(typeof(SortResultOptionFilter));
            FilterUtils2<IOptionFilter>.RegisterFilter(typeof(PaginateOptionFilter));

            FilterUtils2<IEntryFilter>.RegisterIconProvider(typeof(FileTypeEntryFilter), ResourceIconProvider.Instance);                        
        }

        public static void EnablePlugin(string path = null)
        {
            if (path == null)
            {
                var exeAssembly = Assembly.GetExecutingAssembly();
                path = COFEPath.GetDirectoryName(exeAssembly.Location);
            }

            _pluginManager = new PluginManager(path);
        }


        #endregion

        #region Data

        private static IMasterEventLogger _masterEventLogger = null;
        private static IPropertyDictionary _propertyDictionary = null;
        private static IVolumeRegistrar _volumeRegistrar = null;
        private static IUserProfileManager _userProfileManager = null;
        private static IEntryConstructor _entryConstructor = null;
        private static IEntryListRegistrar _entryListRegistrar = null;
        private static IPathParser _pathParser = null;
        private static IEntryTypeDictionary _entryTypeDic = null;
        private static IPluginManager _pluginManager = null;
        private static IEntryOptionFilterParser _filterParser = new FilterParser();
        private static IParamParser _paramParser = new ParamParser();
        
        /// <summary>
        /// The syntax for logging, used by _eventArgs.ToString().
        /// Default {0} = ChangeType, {1} = ItemChanged
        /// </summary>
        public static string LogSyntax = "({0}) - {1}";

        #endregion

        #region Public Properties

        public static IPluginManager PluginManager
        {
            get { return _pluginManager; }
        }

        #region UserProfile
        /// <summary>
        /// Manage user profiles login and creation.
        /// </summary>        
        public static IUserProfileManager UserProfileManager
        {
            get { return _userProfileManager; }
            set
            {
                Assert.IsNotNull(value);
                _userProfileManager = value;
            }
        }

        /// <summary>
        /// Represents the current user
        /// </summary>
        public static IUserProfile CurrentUserProfile { get { return UserProfileManager.CurrentUserProfile; } }


        /// <summary>
        /// For used in notifiedChanges
        /// </summary>        
        public static IUserProfile AdminUserProfile { get { return UserProfileManager.AdminUserProfile; } }
        #endregion

        public static IMasterEventLogger MasterEventLogger
        {
            get { return _masterEventLogger; }
            private set { _masterEventLogger = value; }
        }

        public static IVolumeRegistrar VolumeRegistrar
        {
            get { return _volumeRegistrar; }
            set
            {
                Assert.IsNotNull(value);

                _volumeRegistrar = value;
                COFEShared.VolumeRegistrar.RegisterFactory(new ProfileRootDirectoryListerFactory(ProfileRootDirectoryLister.ProfileRootFactoryKey));
                COFEShared.VolumeRegistrar.RegisterVolume(
                    ProfileRootDirectoryLister.ProfileRootFactoryKey,
                    ProfileRootDirectoryLister.ProfileRootListerKey, VolumeAccessMode.List);


                //if (_volumeRegistrar != null)
                //{
                //    foreach (var ppair in _volumeRegistrar.Factories)
                //        value.RegisterFactory(ppair.Value);
                //    Assert.GreaterOrEqual(value.Factories.Count(), _volumeRegistrar.Factories.Count());

                //    foreach (var ppair in _volumeRegistrar.Volumes)
                //        value.RegisterVolume(ppair.Value);
                //}

                
            }
        }

        public static IEntryListRegistrar EntryListRegistrar
        {
            get { return _entryListRegistrar; }
            set
            {
                Assert.IsNotNull(value);
                _entryListRegistrar = value;
            }
        }

        public static IPropertyDictionary PropertyDictionary
        {
            get { return _propertyDictionary; }
            set
            {
                Assert.IsNotNull(value);
                //Register registered properties to the new PropertyDictionary.
                if (_propertyDictionary != null)
                {
                    foreach (var p in _propertyDictionary.Properties)
                        value.RegisterProperty(p);
                }

                _propertyDictionary = value;
            }
        }

        public static ISecondaryPropertyProviderManager SecondaryPropertyProviderManager { get; set; }
        public static IEntryConstructor EntryConstructor
        {
            get { return _entryConstructor; }
            set
            {
                Assert.IsNotNull(value);
                _entryConstructor = value;
            }
        }
        public static IPathParser PathParser
        {
            get { return _pathParser; }
            set
            {
                Assert.IsNotNull(value);
                _pathParser = value;
            }
        }

        public static IEntryOptionFilterParser FilterParser
        {
            get { return _filterParser; }
            set
            {
                Assert.IsNotNull(value);
                _filterParser = value;
            }
        }

        public static IParamParser ParamParser
        {
            get { return _paramParser; }
            set
            {
                Assert.IsNotNull(value);
                _paramParser = value;
            }
        }

        public static IEntryTypeDictionary EntryTypeDictionary
        {
            get { return _entryTypeDic; }
            set
            {
                Assert.IsNotNull(value);
                _entryTypeDic = value;
            }
        }


        /// <summary>
        /// Event Dispatcher
        /// </summary>
        public static IEventDispatcher<FileSystemEventArgsExA> FileSystemEventDispatcher { get; set; }

        #endregion
    }
}
